package com.htstar.ovms.report.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.htstar.ovms.admin.api.feign.EtpInfoFeign;
import com.htstar.ovms.admin.api.vo.EtpInfoSVo;
import com.htstar.ovms.common.core.util.OvmDateUtil;
import com.htstar.ovms.common.core.util.R;
import com.htstar.ovms.common.core.util.WebUtils;
import com.htstar.ovms.common.security.service.OvmsUser;
import com.htstar.ovms.common.security.util.SecurityUtils;
import com.htstar.ovms.report.api.req.*;
import com.htstar.ovms.report.api.vo.*;
import com.htstar.ovms.report.mapper.AlarmReportMapper;
import com.htstar.ovms.report.mapper.ViolationsNoSingleCarReportMapper;
import com.htstar.ovms.report.service.AlarmReportService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author 金柱
 */
@AllArgsConstructor
@Service
@Slf4j
public class AlarmReportServiceImpl implements AlarmReportService {

    private final EtpInfoFeign etpInfoFeign;
    @Autowired
    private AlarmReportMapper alarmReportMapper;

    /**
     * jinzhu
     * 按月统计 超速越界 次数
     *
     * @param req
     * @return
     */
    @Override
    public R<List<AlarmReportVO>> AlarmReportI(AlarmReportReq req) {
        int AlarmTotals = 0; //统计总月违规 无单次数
        //获取当前用户企业ID
        int etpId = SecurityUtils.getUser().getEtpId();
        //根据本级企业查询本级和下级企业
        if (Objects.equals(req.getEtpId(), null)){ req.setEtpId(etpId);}
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(req.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            req.setEtpIds(etpInfoSVo.getIds());
        });
        //解析日期某年到某年，部门条件
        Map<String, Object> params = new HashMap<>();
        params.put("etpId", req.getEtpIds());
        params.put("status", req.getStatus());
        if (StrUtil.isNotBlank(req.getLicCode())) {
            params.put("dvgIdStar", req.getLicCode());
        }
        params.put("staTime", req.getYearDate() + "-01-01 00:00:00");
        params.put("endTime", req.getYearDate() + "-12-31 23:59:59");
        //查询记录
        //映射变量，返回视图对象VO
        List<AlarmReportVO> list = new ArrayList<>();
        AlarmReportVO vo = null;
        List<AlarmReportsVO> mileaGeTalList = alarmReportMapper.queryMonthAlarmrCount(params);
        for (int i = 1; i <= 12; i++) {
            //映射月份
            vo = new AlarmReportVO();
            vo.setMonthDate(req.getYearDate() + "-" + i);
            //当前月份
            int finalI = i;
            //过滤掉没有的月份数据，显示为0
            Optional<AlarmReportsVO> to = mileaGeTalList
                    .stream()
                    .filter(totalVo -> totalVo.getMd() == finalI).findFirst();
            vo.setAlarmCount(to.isPresent() ? to.get().getAlarmCount() : 0);
            //总次数
            AlarmTotals = AlarmTotals + vo.getAlarmCount();
            list.add(vo);
        }
        List list2 = new ArrayList<>();
        Map msp = new HashMap();
        msp.put("AlarmTotals", AlarmTotals);
        list2.add(list);
        list2.add(msp);
        if (req.getExportStatus() == 1) {
            monthReportExport(list, msp, req.getStatus());
            return null;
        } else {
            return R.ok(list2);
        }
    }

    /**
     * 按车辆统计无单违规用车记录
     *
     * @param req
     * @return
     */
    @Override
    public R<AlarmTotalPageVO> vceCarReport(ByAlarmReportPageReq req) {
        //获取当前登录用户
        OvmsUser user = SecurityUtils.getUser();
        int etpId = user.getEtpId();
        //根据本级企业查询本级和下级企业
        if (Objects.equals(req.getEtpId(), null)){req.setEtpId(etpId);}
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(req.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            req.setEtpIds(etpInfoSVo.getIds());
        });
        //获取数据存入返回前端视图
        AlarmTotalPageVO vo = new AlarmTotalPageVO();
        IPage<AlarmTotalVO> page = alarmReportMapper.queryAlarmUser(req);
        vo.setPage(page);
        ByDrivingReportReq re = new ByDrivingReportReq();
        BeanUtils.copyProperties(req, re);
        List<AlarmTotalVO> vceTotalVOS = alarmReportMapper.queryAlarmUsers(re);
        AlarmTotalVO vo1 = null;
        for (int i = 0; i < vceTotalVOS.size(); i++) {
            vo1 = vceTotalVOS.get(i);
            vo.setAlarmTotal(vo1.getAlarmCount() + vo.getAlarmTotal());
        }
        //导出
        if (req.getExportStatus() == 1) {
            BeanUtils.copyProperties(req, re);
            long count = vceTotalVOS.size();
            req.setSize(count);
            req.setPages(count);
            page.setRecords(alarmReportMapper.queryAlarmCars(re));
            page.setSize(count);
            return vceCarReportExport(page, vo, req.getStatus());
        }
        //app不分页查询
        if(Objects.equals(req.getAppStatus(),1)){
            long count =vceTotalVOS.size();
            req.setSize(count);
            req.setPages(count);
            page.setRecords(alarmReportMapper.queryAlarmCars(re));
            page.setSize(count);
            vo.setPage(page);
        }
        return R.ok(vo);
    }

    /**
     * 按人员统计无单违规用车记录
     *
     * @param req
     * @return
     */
    @Override
    public R<AlarmTotalPageVO> vceUserReport(ByAlarmReportPageReq req) {
        //获取当前登录用户
        OvmsUser user = SecurityUtils.getUser();
        int etpId = user.getEtpId();
        //根据本级企业查询本级和下级企业
        if (Objects.equals(req.getEtpId(), null)){req.setEtpId(etpId);}
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(req.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            req.setEtpIds(etpInfoSVo.getIds());
        });
        //获取数据存入返回前端视图
        AlarmTotalPageVO vo = new AlarmTotalPageVO();
        IPage<AlarmTotalVO> page = alarmReportMapper.queryAlarmCar(req);
  
        vo.setPage(page);
        ByDrivingReportReq re = new ByDrivingReportReq();
        BeanUtils.copyProperties(req, re);
        List<AlarmTotalVO> vceTotalVOS = alarmReportMapper.queryAlarmCars(re);
        AlarmTotalVO vo1 = null;
        for (int i = 0; i < vceTotalVOS.size(); i++) {
            vo1 = vceTotalVOS.get(i);
            vo.setAlarmTotal(vo1.getAlarmCount() + vo.getAlarmTotal());
        }
        //导出
        if (req.getExportStatus() == 1) {
            BeanUtils.copyProperties(req, re);
            long count = vceTotalVOS.size();
            req.setSize(count);
            req.setPages(count);
            page.setRecords(alarmReportMapper.queryAlarmCars(re));
            page.setSize(count);
            return vceUserReportExport(page, vo, req.getStatus());
        }
        //app不分页查询
        if (Objects.equals(req.getAppStatus(),1)) {
            BeanUtils.copyProperties(req, re);
            long count = vceTotalVOS.size();
            req.setSize(count);
            req.setPages(count);
            page.setRecords(alarmReportMapper.queryAlarmCars(re));
            page.setSize(count);
            vo.setPage(page);
        }
        return R.ok(vo);
    }

    /**
     * 按月份导出超速 越界记录
     *
     * @param list
     * @return
     */
    public R monthReportExport(List<AlarmReportVO> list, Map map, Integer status) {
        //获取客户端响应
        HttpServletResponse response = WebUtils.getResponse();
        //开启写入写出器
        ExcelWriter writer = ExcelUtil.getWriter(true);
        if (Objects.equals(status, 1)) {
            writer.renameSheet("月份报表超速报警记录");
        } else {
            writer.renameSheet("月份报表越界报警记录");
        }
        //返回为空，因为如果返回响应的话，就提交了二次会报 UT010019: Response already commited
        if (list == null || list.isEmpty()) {
            return null;
        }
        List<Map<String, Object>> rows = new ArrayList<>();
        List<Map<String, Object>> rows1 = new ArrayList<>();
        Map<String, Object> row1 = new LinkedHashMap<>();
        row1.put("/", "总计：");
        if (Objects.equals(status, 1)) {
            row1.put("超速报警总次数", map.get("AlarmTotals"));
        } else {
            row1.put("越界报警总次数", map.get("AlarmTotals"));
        }

        rows1.add(row1);
        //写入数据
        writer.write(rows1, true);
        //传输不能拿实体类，传输视图数据可以用vo
        for (AlarmReportVO vo : list) {
            //导出数据利用HashMap是无序的，要用LinkedHashMap有序
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("月份", vo.getMonthDate());
            if (Objects.equals(status, 1)) {
                row.put("超速报警次数", vo.getAlarmCount());
            } else {
                row.put("越界报警次数", vo.getAlarmCount());
            }
            rows.add(row);
        }
        writer.write(rows, true); //写入数据
        OutputStream out = null; //输出流
        try {
            //设置响应格式显示为excel
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            if (Objects.equals(status, 1)) {
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                        "超速报警报表-按月统计" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            } else {
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                        "越界报警报表-按月统计" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            }
            out = response.getOutputStream();//输出流响应
            writer.flush(out, true);//开启缓冲
        } catch (IOException e) {
            log.error("超速越界报表-按月统计", e);
        } finally {
            writer.close(); //关不输入输出
            IoUtil.close(out);//关闭io流

        }
        return null; //返回为空，因为如果返回有响应的话，就提交了二次会报 UT010019: Response already commited
    }

    /**
     * 按车辆导出超速越界记录
     *
     * @param page
     * @return
     */
    public R vceCarReportExport(IPage<AlarmTotalVO> page, AlarmTotalPageVO vo, Integer status) {
        HttpServletResponse response = WebUtils.getResponse();
        ExcelWriter writer = new ExcelWriter();
        if (Objects.equals(status, 1)) {
            writer.renameSheet("车辆报表超速报警记录");
        } else {
            writer.renameSheet("车辆报表越界报警记录");
        }
        if (page == null && page.getRecords().size() <= 0) {
            return null;
        }
        List<Map<String, Object>> rows = new ArrayList<>();
        List<Map<String, Object>> rows1 = new ArrayList<>();
        Map<String, Object> row1 = new LinkedHashMap<>();
        row1.put("/", "总计：");
        if (Objects.equals(status, 1)) {
            row1.put("超速报警总次数", vo.getAlarmTotal());
        } else {
            row1.put("越界报警总次数", vo.getAlarmTotal());
        }
        rows1.add(row1);
        writer.write(rows1, true);//写入数据
        AlarmTotalVO vo1 = null;
        for (int i = 0; i < page.getRecords().size(); i++) {
            Map<String, Object> row = new LinkedHashMap<>();
            vo1 = page.getRecords().get(i);
            row.put("机构", vo1.getEtpName());
            row.put("车牌号", vo1.getVce());
            if (Objects.equals(status, 1)) {
                row.put("超速报警次数", vo1.getAlarmCount());
            } else {
                row.put("越界报警次数", vo1.getAlarmCount()
                );
            }
            rows.add(row);
        }
        writer.write(rows, true);//写入数据
        OutputStream out = null;
        try {
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            if (Objects.equals(status, 1)) {
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                        "超速报警报表-按车辆统计" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            } else {
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                        "越界报警报表-按车辆统计" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            }
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (Exception e) {
            log.error("超速越界报表-按车辆统计", e);
        } finally {
            writer.close(); //关不输入输出
            IoUtil.close(out);//关闭io流

        }
        return null;
    }

    /**
     * 按车辆导出超速越界记录
     *
     * @param page
     * @return
     */
    public R vceUserReportExport(IPage<AlarmTotalVO> page, AlarmTotalPageVO vo, Integer status) {
        HttpServletResponse response = WebUtils.getResponse();
        ExcelWriter writer = new ExcelWriter();
        if (Objects.equals(status, 1)) {
            writer.renameSheet("人员报表超速报警记录");
        } else {
            writer.renameSheet("人员报表越界报警记录");
        }
        if (page == null && page.getRecords().size() <= 0) {
            return null;
        }
        List<Map<String, Object>> rows = new ArrayList<>();
        List<Map<String, Object>> rows1 = new ArrayList<>();
        Map<String, Object> row1 = new LinkedHashMap<>();
        row1.put("/", "总计：");
        if (Objects.equals(status, 1)) {
            row1.put("超速报警总次数", vo.getAlarmTotal());
        } else {
            row1.put("越界报警总次数", vo.getAlarmTotal());
        }
        rows1.add(row1);
        writer.write(rows1, true);//写入数据
        AlarmTotalVO vo1 = null;
        for (int i = 0; i < page.getRecords().size(); i++) {
            Map<String, Object> row = new LinkedHashMap<>();
            vo1 = page.getRecords().get(i);
            row.put("机构", vo1.getEtpName());
            row.put("车牌号", vo1.getVce());
            if (Objects.equals(status, 1)) {
                row.put("超速报警次数", vo1.getAlarmCount());
            } else {
                row.put("越界报警次数", vo1.getAlarmCount()
                );
            }
            rows.add(row);
        }
        writer.write(rows, true);//写入数据
        OutputStream out = null;
        try {
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            if (Objects.equals(status, 1)) {
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                        "超速报警报表-按人员统计" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            } else {
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(
                        "越界报警报表-按人员统计" + OvmDateUtil.getCstNowDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        , "UTF-8").getBytes("UTF-8"), "ISO8859-1") + ".xlsx");
            }
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (Exception e) {
            log.error("超速越界报表-按人员统计", e);
        } finally {
            writer.close(); //关不输入输出
            IoUtil.close(out);//关闭io流

        }
        return null;
    }
}
